<?php namespace xlx;

//监视服务添加一个监视（init在主进程）
class DbSupervisor
{  
    //异步等待返回coid 类设计错误 没办法做start_link
    public static function start($class_fn,$args=[])
    {
        $pid = yield \xlx\AChannel::make($actor,$s);  
        if(is_string($class_fn )){
            $class_fn = [$class_fn,'init'];
        }
        if($class_fn instanceof \Closure){
            $class_fn = (serialize(new \Opis\Closure\SerializableClosure($class_fn)) );
        } 
        //链接服务池 不链接本地
        yield $actor->send('danboo.server',['SUP_START' , $class_fn , $pid ]); 
        return yield $actor->receive();   
    }
    
 



    public static function init($super,$args){ 
        // return [
        //     [opt],
        //     [W1::class]
        // ];
    }





    /**
     * 启动子进程（重新启动？）
     * @param [type] $name 监视进程coid
     * @param [type] $args 子进程init参数
     * @return void 子进程coid
     */
    public static function start_child($coid,$args=[])
    {
        //yield \xlx\AChannel::make($actor,$s);  

        if($proc = \xlx\Danboo::$data_server['coids'][$coid]){
            $opt = $proc->childsdesc; 

        }

        //$actor->spawn();
        //yield $actor->send('danboo.sup',['start_child',$coid,$args,$actor->self()]); 
        //return yield $self->receive();
    } 
    /**
     * 停止进程（监视会自动重启）
     * @param string $coid 监视进程coid
     * @param string $index 子进程序号（0开始）
     * @return void 
     */
    public static function delete_child($coid,$index)
    {
        return self::getChannel()->call(['DSUPERVISOR',$name,$atom]); 
    } 
    /**
     * 停止监视（等待自动结束）   
     * @param string $coid 监视进程coid
     * @param string $index 子进程序号（0开始）
     * @return void
     */
    public static function terminate_child($coid,$index){

    }
 



    //0:TOKEN 1:func 2:args
    public function __construct( $coid,$item) { 
        $this->coid = $coid;
        $this->item = $item;
        $this->childsdesc = [];
        $config = call_user_func($item[1],$this);//, $item[2]
        // if(isset($config)){
        //     $this->option = $config[0]??[];
        //     $this->childsdesc = $config[1]??[]; 
        // }  
    }
    public function restart(){ 
        return \xlx\co(function() { 
            if(!count($this->childsdesc)){
                return;
            }
            yield \xlx\AChannel::make($actor,$stack);  
            foreach ($this->childsdesc as $index => $value){ 
                $pid = yield $actor->{$value['type']}($value['class'],$this->item[2]); 
                $this->process[$pid] = $index;
                $this->link( $pid ); 
            }  
        });
    }

    //tcp connection postmessage interface
    public function send($item){
        switch ($item[0]) {
            case 'EXIT'://0:TOKEN  1:DIE , 2:GEN_TOKEN  ,3:FROM  
                \xlx\co(function()use($item){  
                    $index = $this->process[$item[3]];
                    $value = $this->childsdesc[$index]; 
                    $pid = yield $this->{$value['type']}($value['class'],$item[2]); 
                    $this->process[$pid] = $index;
                    $this->link( $pid );   
                });
                break; 
            default:
                # code...
                break;
        }
    }

    public function link($pid){
        \xlx\Danboo::$data_server['link'][$pid][$this->coid]=true; 
    }

    public function flags($option){

    }

    /** 
     * @param [type] $classOrfunc 启动函数
     * @param [type] $restart 重启方式
     * @param [type] $delay 重启间隔
     * @return void
     */
    public function worker($classOrfunc,$restart=0,$delay=0){ 
        $this->childsdesc[] = ['type'=>'spawn','class'=>$classOrfunc];
    }

    /** 
     * @param [type] $classOrfunc 启动函数
     * @param [type] $restart 重启方式
     * @param [type] $delay 重启间隔
     * @return void
     */
    public function service($classOrfunc,$restart=0,$delay=0){
        $this->childsdesc[] = ['type'=>\xlx\DbService::class,'class'=>$classOrfunc];
    }
    /** 
     * @param [type] $classOrfunc 启动函数
     * @param [type] $restart 重启方式
     * @param [type] $delay 重启间隔
     * @return void
     */
    public function supervisor($classOrfunc,$restart,$delay){
        
    }
    
    public function __debugInfo(){
        return ['coid'=>$this->coid];
    }




    public static function onstartchild($coid,$class,$option){ 
        echo "\r!!";
        \xlx\Process::fork(function()use($coid,$class,$option){
            echo "\r@@";
            yield \xlx\AChannel::make($actor,$s); 
            echo "\r##";
            yield $actor->link($coid,$class);
            yield $class::init($actor,$option);
        });
    }
}

